package com.dailyyoga.bitmapManager;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.ref.WeakReference;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.util.LruCache;
import android.util.Log;
import android.widget.ImageView;

import com.dailyyoga.view.RecyclingImageView;
import com.net.tool.BgkTaskMange;
import com.net.tool.DownLoadTask;
import com.net.tool.DownloadIconTask;
import com.net.tool.ExAsyncTask;
import com.tools.BitmapUtile;

public class YogaImageLoader {

	// 定义一级 缓存的图片数

	// private static ConcurrentHashMap<String, SoftReference<Bitmap>>
	// current_hashmap;

	// 定义一级缓存容器 强引用 (catch_num ,0.75f,true） 默认参数 2.加载因子默认 3.排序模式 true
	private static LruCache<String, RecyclingBitmapDrawable> mMemoryCache;

	public static interface ImageLoaderListener {

		public static final int COMPLATE_SUCCESS = 1;
		public static final int COMPLATE_HAS = 2;
		public static final int COMPLATE_FAILED = 0;

		public void updateProgress(int progress, int length);

		public void complate(int state);
	}

	static Map<String, ImageLoaderListener> mListenerMap;

	Context mContext;

	int mW;
	int mH;

	public YogaImageLoader(Context context) {
		mContext = context;
		mW = mContext.getResources().getDisplayMetrics().widthPixels;
		mH = mContext.getResources().getDisplayMetrics().heightPixels;

		if (mListenerMap == null) {
			mListenerMap = new HashMap<String, YogaImageLoader.ImageLoaderListener>();
		}

		if (mMemoryCache == null) {

			int cacheSize = 0;

			if (Build.VERSION.SDK_INT < 10) {
				cacheSize = 1024 * 1024;
			} else {

				int maxMemory = (int) (Runtime.getRuntime().maxMemory());
				cacheSize = maxMemory / 8;
			}

			Log.d("cacheSize", "cacheSize=" + cacheSize);

			mMemoryCache = new LruCache<String, RecyclingBitmapDrawable>(
					cacheSize) {
				protected void entryRemoved(boolean evicted, String key,
						RecyclingBitmapDrawable oldValue,
						RecyclingBitmapDrawable newValue) {

					oldValue.setIsCached(false);

				}

				protected int sizeOf(String key, RecyclingBitmapDrawable value) {

					Bitmap bitmap = value.getBitmap();

					if (bitmap != null) {
						int bitmapSize = bitmap.getRowBytes()
								* bitmap.getHeight();
						return bitmapSize == 0 ? 1 : bitmapSize;
					}

					return 1;
				}
			};
		}

	}

	static int mDefault = -1;

	static Bitmap mBuffBitmap;

	/**
	 * 外部调用此方法 进行下载图片
	 */
	public void downLoad(String key, RecyclingImageView imageView,
			int defultIcon) {

		Log.d("YogaImageLoader", "url=" + key);

		RecyclingBitmapDrawable bitmap = getBitmapFromCache(key);
		if (null != bitmap) {
			imageView.setImageDrawable(bitmap);
			imageView.setCachePath(DownLoadTask.path + getMD5Str(key));

			cancleFile(key, imageView); // 取消下载
			return;
		}

		if (defultIcon != mDefault) {
			mBuffBitmap = BitmapFactory.decodeResource(mContext.getResources(),
					defultIcon);
			mDefault = defultIcon;
		}

		if (key.contains("tou.jpg") || key.contains("tou2.jpg")
				|| key.contains("tou1.jpg")) {

			imageView.setImageBitmap(mBuffBitmap);

		} else if (cancleFile(key, imageView)) { // 没有任务进行。，。。开始下载

			ImageFileTask task = new ImageFileTask(imageView);
			FileImage zhanwei_image = new FileImage(task, mBuffBitmap);
			imageView.setImageDrawable(zhanwei_image);
			task.execute(key);
		}
	}

	/**
	 * 外部调用此方法 进行下载图片
	 */
	public void downLoad(String key, RecyclingImageView imageView,
			int defultIcon, ImageLoaderListener loaderListener) {

		assert (loaderListener != null);

		Log.d("YogaImageLoader", "url=" + key);

		RecyclingBitmapDrawable bitmap = getBitmapFromCache(key);
		if (null != bitmap) {
			imageView.setImageDrawable(bitmap);
			imageView.setCachePath(DownLoadTask.path + getMD5Str(key));
			cancleFile(key, imageView); // 取消下载
			loaderListener.complate(ImageLoaderListener.COMPLATE_HAS);
			return;
		}

		if (defultIcon != mDefault) {
			mBuffBitmap = BitmapFactory.decodeResource(mContext.getResources(),
					defultIcon);
			mDefault = defultIcon;
		}

		if (key.contains("tou.jpg") || key.contains("tou2.jpg")
				|| key.contains("tou1.jpg")) {

			imageView.setImageBitmap(mBuffBitmap);
			loaderListener.complate(ImageLoaderListener.COMPLATE_HAS);

		} else if (cancleFile(key, imageView)) { // 没有任务进行。，。。开始下载

			mListenerMap.put(key, loaderListener);
			ImageFileTask task = new ImageFileTask(imageView);
			FileImage zhanwei_image = new FileImage(task, mBuffBitmap);
			imageView.setImageDrawable(zhanwei_image);
			task.execute(key);
		}
	}

	public void downLoad(String key, RecyclingImageView imageView, int w,
			int h, int defultIcon) {
		mW = w;
		mH = h;
		downLoad(key, imageView, defultIcon);
	}

	/**
	 * 此方法 用于优化 ： 用户直接 翻到 哪个 就先加载 哪个、
	 * 
	 * @param key
	 *            - URL
	 * @param imageView
	 *            - imageView core： 给当前的 imageView 得到给他下载的 task
	 */

	boolean cancleFile(String key, ImageView imageView) {
		// 给当前的 imageView 得到给他下载的 task
		ImageFileTask task = getImageFileTask(imageView);
		if (null != task) {
			String down_key = task.key;
			if (null == down_key || !down_key.equals(key)) {
				task.cancel(true); // imageview 和 url 的key不一样 取消下载
			} else {
				return false; // 正在下载：
			}
		}
		return true; // 没有正在下载
	}

	boolean cancleDownload(String key, ImageView imageView) {
		// 给当前的 imageView 得到给他下载的 task
		ImageDownloadTask task = getImageDownloadTask(imageView);
		if (null != task) {
			String down_key = task.mUrl;
			if (null == down_key || !down_key.equals(key)) {
				BgkTaskMange.getInstance().executeCommend(task);
			} else {
				return false; // 正在下载：
			}
		}
		return true; // 没有正在下载
	}

	/**
	 * 从缓存中得到 图片的方法 1.先从一级 缓存找 linkhashmap 不是线程安全的 必须要加同步
	 */
	public RecyclingBitmapDrawable getBitmapFromCache(String key) {
		// 1.先在一级缓存中找
		synchronized (mMemoryCache) {
			RecyclingBitmapDrawable bitmap = mMemoryCache.get(key);
			return bitmap;
		}

	}

	/**
	 * 从外部文件缓存中获取bitmap
	 * 
	 * @param url
	 * @return
	 */
	RecyclingBitmapDrawable getBitmapFromFile(String url) {
		Bitmap bitmap = null;
		String fileName = getMD5Str(url);
		if (fileName == null) {
			return null;
		}
		String filePath = DownLoadTask.path + fileName;
		BitmapUtile bitmapUtile = BitmapUtile.getBitmapUtile();
		bitmap = bitmapUtile.decodeBitmap(filePath, mW, mH);

		if (bitmap == null) {

			return null;

		}

		System.out.println("在本地缓存中找到图片===" + filePath);

		RecyclingBitmapDrawable bitmapDrawable = new RecyclingBitmapDrawable(
				mContext.getResources(), bitmap);

		bitmapDrawable.setIsCached(true);

		return bitmapDrawable;

	}

	/**
	 * MD5 加密
	 */
	protected static String getMD5Str(String str) {
		MessageDigest messageDigest = null;
		try {
			messageDigest = MessageDigest.getInstance("MD5");
			messageDigest.reset();
			messageDigest.update(str.getBytes("UTF-8"));
		} catch (NoSuchAlgorithmException e) {
			System.out.println("NoSuchAlgorithmException caught!");
			return null;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return null;
		}

		byte[] byteArray = messageDigest.digest();
		StringBuffer md5StrBuff = new StringBuffer();
		for (int i = 0; i < byteArray.length; i++) {
			if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
				md5StrBuff.append("0").append(
						Integer.toHexString(0xFF & byteArray[i]));
			else
				md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
		}
		return md5StrBuff.toString();
	}

	// ------------------------ 异步加载----------------------------
	/**
	 * 占位的 图片 或者 颜色 用来绑定 相应的图片
	 */
	class FileImage extends BitmapDrawable {
		// 里面存放 相应 的异步 处理时加载好的图片 ----- 相应的 task
		private final WeakReference<ImageFileTask> taskReference;

		@SuppressWarnings("deprecation")
		public FileImage(ImageFileTask task, Bitmap bitmap) {
			super(bitmap);
			taskReference = new WeakReference<YogaImageLoader.ImageFileTask>(
					task);
		}

		// 返回去这个 task 用于比较
		public ImageFileTask getImageFileTask() {
			return taskReference.get();
		}
	}

	// 根据 给 的 iamgeView、 得到里面的 task 用于和当前的 task比较是不是同1个
	private ImageFileTask getImageFileTask(ImageView imageView) {
		if (null != imageView) {
			Drawable drawable = imageView.getDrawable();
			if (drawable instanceof FileImage)
				return ((FileImage) drawable).getImageFileTask();

		}
		return null;
	}

	class DownLoadIamge extends BitmapDrawable {
		// 里面存放 相应 的异步 处理时加载好的图片 ----- 相应的 task
		private final WeakReference<ImageDownloadTask> taskReference;

		@SuppressWarnings("deprecation")
		public DownLoadIamge(ImageDownloadTask task, Bitmap bitmap) {
			super(bitmap);
			taskReference = new WeakReference<YogaImageLoader.ImageDownloadTask>(
					task);
		}

		// 返回去这个 task 用于比较
		public ImageDownloadTask getImageDownloadTask() {
			return taskReference.get();
		}
	}

	// 根据 给 的 iamgeView、 得到里面的 task 用于和当前的 task比较是不是同1个
	private ImageDownloadTask getImageDownloadTask(ImageView imageView) {

		if (null != imageView) {
			Drawable drawable = imageView.getDrawable();
			if (drawable instanceof DownLoadIamge)
				return ((DownLoadIamge) drawable).getImageDownloadTask();

		}
		return null;
	}

	/**
	 * 把图片 添加到缓存中
	 */
	private void addBitmap(String key, RecyclingBitmapDrawable bitmap) {
		if (null != bitmap) {
			synchronized (mMemoryCache) { // 添加到一级 缓存中
				mMemoryCache.put(key, bitmap);

			}
		}
	}

	/**
	 * 在后台 加载每个图片 第一个参数 第2个要进度条不 第三个返回结果 bitmap
	 */
	class ImageFileTask extends
			ExAsyncTask<String, Void, RecyclingBitmapDrawable> {

		private String key;
		private WeakReference<RecyclingImageView> imgViReference;

		public ImageFileTask(RecyclingImageView imageView) {
			// imageView 传进来 。。要给哪个iamgeView加载图片
			imgViReference = new WeakReference<RecyclingImageView>(imageView);
		}

		protected RecyclingBitmapDrawable doInBackground(String... params) {
			key = params[0];
			// 调用下载函数 根据 url 下载
			return getBitmapFromFile(key);
		}

		protected void onPostExecute(RecyclingBitmapDrawable result) {

			ImageLoaderListener listener = mListenerMap.get(key);

			RecyclingImageView imageView = imgViReference.get();

			if (null != result) {
				// 保存到缓存中
				addBitmap(key, result);
				mListenerMap.remove(key);
				if (null != imageView) {
					// 向 imageView 里面放入 bitmap
					ImageFileTask task = getImageFileTask(imageView);
					/**
					 * 判断 是不是 同一个 task( ) 如果当前这个 task == imageView 里面的那个 task
					 * 就是同1个
					 */
					if (this == task) {
						imageView.setImageDrawable(result);
						imageView.setCachePath(DownLoadTask.path
								+ getMD5Str(key));
					}

				}
				if (listener != null) {
					listener.complate(ImageLoaderListener.COMPLATE_SUCCESS);
				}

			} else if (imageView != null) {
				// 缓存中 没有 把当前的 imageView 给他 得到 task
				if (cancleDownload(key, imageView)) { // 没有任务进行。，。。开始下载
					ImageDownloadTask task = new ImageDownloadTask(key,
							imageView);

					task.setImageLoaderListener(listener);

					DownLoadIamge zhanwei_image = new DownLoadIamge(task,
							mBuffBitmap);
					// 先把占位的图片放进去
					imageView.setImageDrawable(zhanwei_image);
					Log.d("YogaImageLoader", "执行下载");
					BgkTaskMange.getInstance().executeDownloadTask(task);

				}
			}
		}
	}

	class ImageDownloadTask extends DownloadIconTask {

		RecyclingBitmapDrawable mBitmap;
		private WeakReference<RecyclingImageView> imgViReference;

		public ImageDownloadTask(String url, RecyclingImageView imageView) {
			super(url);
			imgViReference = new WeakReference<RecyclingImageView>(imageView);
		}

		public void download(String URl) throws IOException {

			synchronized ("ImageDownloadTask") {

				try {
					downloadBitMap(URl);
					mBitmap = getBitmapFromFile(URl);

				} catch (Exception e) {
					e.printStackTrace();
				}
			}

		}

		public void gbkPostUI() {
			ImageLoaderListener listener = mListenerMap.get(mUrl);
			mListenerMap.remove(mUrl);
			if (mBitmap != null) {

				addBitmap(mUrl, mBitmap);

				RecyclingImageView imageView = imgViReference.get();

				if (null != imageView) {
					// 向 imageView 里面放入 bitmap
					ImageDownloadTask task = getImageDownloadTask(imageView);
					/**
					 * 判断 是不是 同一个 task( ) 如果当前这个 task == imageView 里面的那个 task
					 * 就是同1个
					 */
					if (this == task) {
						imageView.setImageDrawable(mBitmap);
						imageView.setCachePath(DownLoadTask.path
								+ getMD5Str(mUrl));
					}
				}

				if (listener != null) {
					listener.complate(ImageLoaderListener.COMPLATE_SUCCESS);
				}

			} else {

				if (listener != null) {
					listener.complate(ImageLoaderListener.COMPLATE_FAILED);
				}
			}

		}

	}

	public void clearCache() {

	}
}
